package com.usian.admin.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sun.tools.javac.util.Pair;
import com.usian.admin.feign.ArticleFeign;
import com.usian.admin.feign.WemediaFeign;
import com.usian.admin.mapper.AdChannelMapper;
import com.usian.admin.mapper.AdSensitiveMapper;
import com.usian.admin.service.WemediaNewsAutoScanService;
import com.usian.common.aliyun.scan.GreeTextScan;
import com.usian.common.aliyun.scan.GreenImageScan;
import com.usian.common.fastdfs.FastDFSClient;
import com.usian.common.wemedia.WemediaContans;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.admin.pojos.AdChannel;
import com.usian.model.admin.pojos.AdSensitive;
import com.usian.model.article.pojos.ApArticle;
import com.usian.model.article.pojos.ApArticleConfig;
import com.usian.model.article.pojos.ApArticleContent;
import com.usian.model.base.BaseServiceImpl;
import com.usian.model.common.dtos.PageResponseResult;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.media.pojos.WmNews;
import com.usian.model.media.pojos.WmUser;
import com.usian.model.media.vo.WmNewsVo;
import com.usian.utils.common.SensitiveWordUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Service
public class WemediaNewsAutoScanServiceImpl extends BaseServiceImpl<AdSensitiveMapper, AdSensitive> implements WemediaNewsAutoScanService {
    @Autowired
    private WemediaFeign wemediaFeign;
    @Autowired
    private ArticleFeign articleFeign;
    @Value("${fdfs.url}")
    private String baseUrl;
    @Autowired
    private GreenImageScan greenImageScan;
    @Autowired
    private GreeTextScan greeTextScan;
    @Autowired
    private FastDFSClient fastDFSClient;
    @Autowired
    private AdChannelMapper adChannelMapper;

    private short resultStatus = WmNews.Status.PUBLISHED.getCode();
    private String reason = "审核通过";

    @Override
    public ResponseResult autoScanByMediaNewsId(Integer id) {
        if (id == null) return errorParam;
        boolean isGoing = true;
        WmNews news = wemediaFeign.findById(id);
        if (news.getStatus().equals(WmNews.Status.ADMIN_SUCCESS.getCode()) ||
                (news.getStatus().equals(WmNews.Status.SUCCESS.getCode()) && news.getPublishTime().getTime() <= System.currentTimeMillis())

        ) {
            saveArticleInfo(news);
            updateNewsStatus(news, reason, resultStatus);
        }
        if (news.getStatus() == WmNews.Status.SUBMIT.getCode()) {//提交待审核的情况
            Pair<StringBuffer, List<String>> controlData = getControlData(news);
            String text = controlData.fst.toString();
            //文本的自动审核
            try {
                Map map = greeTextScan.greeTextScan(text);
                isGoing = isGoing(map, news);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //图片自动审核
            if (isGoing) {//说明文本审核通过了
                isGoing = isGoing(imageAutoScan(controlData.snd), news);
            }
            //敏感词匹配
            if (isGoing) {
                List<String> allSensitive = baseMapper.findAllSensitive();
                SensitiveWordUtil.initMap(allSensitive);
                Map<String, Integer> map = SensitiveWordUtil.matchWords(text);
                if (map.size() != 0) {//有敏感词
                    Map<String, Object> tempMap = new HashMap<>();
                    tempMap.put("suggestion", "block");
                    isGoing = isGoing(tempMap, news);
                }
            }
        }
        if (isGoing) {//自动审核通过
            if (news.getPublishTime().getTime() <= System.currentTimeMillis()) {
                saveArticleInfo(news);
            } else {
                reason = "审核通过待发布";
                resultStatus = WmNews.Status.SUCCESS.getCode();
                updateNewsStatus(news, reason, resultStatus);
            }
        }
        return isGoing ? ResponseResult.okResult(reason) : ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, reason);
    }

    private void saveArticleInfo(WmNews news) {
        ApArticle article = saveArticle(news);
        saveArticleConfig(article);
        saveArticleContent(article, news);
        updateNewsStatus(news, reason, resultStatus);
    }

    //从新闻内容中提取要审核的文本和图片
    private Pair<StringBuffer, List<String>> getControlData(WmNews news) {
        String content = news.getContent();
        JSONArray array = JSONArray.parseArray(content);
        //这个用来拼接内容中的文本
        StringBuffer buffer = new StringBuffer();
        //这个用来保存内容中的图片路径
        List<String> urList = new ArrayList<>();
        array.forEach(a -> {
            //得到大括号里面的值
            JSONObject object = JSON.parseObject(a.toString());
            //如果是图片的话就加入urlist
            String value = object.getString("value");
            if (object.get("type").equals("image")) {
                urList.add(value.replace(baseUrl, ""));
            } else {
                //文本的话就加入buffer
                buffer.append(value);
            }
        });
        //判断图片类型是单图还是多图
        if (news.getType() == WemediaContans.WM_NEWS_SINGLE_IMAGE) {
            urList.add(news.getImages().replace(baseUrl, ""));
        } else if (news.getType() == WemediaContans.WM_NEWS_MANY_IMAGE) {
            String[] split = news.getImages().split(",");
            for (String s : split) {
                urList.add(s.replace(baseUrl, ""));
            }
        }
        return new Pair(buffer, urList);
    }

    //图片自动审核
    private Map imageAutoScan(List<String> urList) {
        List<byte[]> bytes = new ArrayList<>();
        for (String s : urList) {
            int i = s.indexOf("/");
            String groupName = s.substring(0, i);
            s += "0";
            String path = s.substring(i + 1, s.length() - 1);
            try {
                byte[] download = fastDFSClient.download(groupName, path);
                bytes.add(download);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        Map map = null;
        try {
            map = greenImageScan.imageScan(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    //保存
    private void saveArticleContent(ApArticle article, WmNews news) {
        ApArticleContent content = new ApArticleContent();
        content.setArticleId(article.getId());
        content.setContent(news.getContent());
        articleFeign.saveArticleContent(content);
    }

    private void saveArticleConfig(ApArticle article) {
        ApArticleConfig config = new ApArticleConfig();
        config.setArticleId(article.getId());
        config.setIsComment(false);
        config.setIsForward(false);
        config.setIsDelete(false);
        config.setIsDown(false);
        articleFeign.saveArticleConfig(config);
    }

    private ApArticle saveArticle(WmNews news) {
        Integer userId = news.getUserId();//自媒体人id
        WmUser wmUser = wemediaFeign.getUserById(userId);
        ApArticle article = new ApArticle();
        AdChannel adChannel = adChannelMapper.selectById(news.getChannelId());
        article.setTitle(news.getTitle());
        article.setAuthorId(wmUser.getApAuthorId());
        article.setAuthorName(wmUser.getName());
        article.setChannelId(news.getChannelId());
        article.setChannelName(adChannel.getName());
        article.setLayout(news.getType());
        if (news.getType() == WemediaContans.WM_NEWS_MANY_IMAGE) article.setLayout((short) 2);
        article.setFlag((byte) 0);
        article.setImages(news.getImages());
        article.setLikes(0);
        article.setComment(0);
        article.setViews(0);
        article.setCollection(0);
        article.setCreatedTime(news.getCreatedTime());
        article.setPublishTime(news.getPublishTime());
        return articleFeign.saveArticle(article);
    }

    private boolean isGoing(Map map, WmNews news) {
        if (map == null) return false;
        if (!map.get("suggestion").equals("pass")) {
            if (map.get("suggestion").equals("block")) {//建议拒绝
                reason = "自动审核失败";
                resultStatus = WmNews.Status.FAIL.getCode();
                updateNewsStatus(news, reason, resultStatus);
            } else if (map.get("suggestion").equals("review")) {
                reason = "需要人工审核";
                resultStatus = WmNews.Status.ADMIN_AUTH.getCode();
                updateNewsStatus(news, reason, resultStatus);
            }
            return false;
        }
        return true;
    }

    private void updateNewsStatus(WmNews news, String reason, short status) {
        WmNews updateNews = new WmNews();
        updateNews.setId(news.getId());
        updateNews.setReason(reason);
        updateNews.setStatus(status);
        wemediaFeign.updateWmNews(updateNews);
    }
    @Override
    public PageResponseResult findNews(NewsAuthDto dto) {
        //分页查询
        PageResponseResult responseResult =  wemediaFeign.findList(dto);
        //有图片需要显示，需要fasfdfs服务器地址
        responseResult.setHost(baseUrl);
        return responseResult;
    }

    @Override
    public ResponseResult findOne(Integer id) {
        //1参数检查
        if(id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2查询数据
        WmNewsVo wmNewsVo = wemediaFeign.findWmNewsVo(id);
        //结构封装
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        responseResult.setHost(baseUrl);
        return responseResult;
    }

    @Override
    public ResponseResult updateStatus(Integer type, NewsAuthDto dto) {
        //1.参数检查
        if(dto == null || dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2.查询文章
        WmNews wmNews = wemediaFeign.findById(dto.getId());
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //3.审核没有通过
        if(type.equals(0)){
            updateNewsStatus(wmNews,reason,resultStatus);
        }else if(type.equals(1)){
            //4.人工审核通过
            updateNewsStatus(wmNews,reason,resultStatus);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
